package com.tuzhi.gateway.filter;

import com.alibaba.fastjson2.JSON;
import com.tuzhi.auth.sys.config.ConstantConfig;
import com.tuzhi.auth.sys.scurity.AuthService;
import com.tuzhi.auth.sys.scurity.AuthTokenService;
import com.tuzhi.auth.sys.scurity.impl.TokenServiceImpl;
import com.tuzhi.base.web.helper.AjaxResultHelper;
import com.tuzhi.base.web.util.ServletUtil;
import com.tuzhi.common.constants.AppConstant;
import com.tuzhi.common.constants.ResultConstant;
import com.tuzhi.common.domain.LoginUserBO;
import com.tuzhi.common.domain.ResultBO;
import com.tuzhi.common.helper.ResultHelper;
import com.tuzhi.gateway.config.GatewayConfig;
import com.tuzhi.gateway.httpclient.face.AuthApi;
import com.tuzhi.gateway.service.ResServiceImpl;
import com.tuzhi.gateway.utils.ServletUtils;
import com.tuzhi.util.ListTzUtil;
import com.tuzhi.util.NumberTzUtil;
import com.tuzhi.util.StringTzUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static com.tuzhi.common.constants.security.Constants.AUTHORIZE_TOKEN;
import static com.tuzhi.common.constants.security.Constants.USER_INFO;

/**
 * 给每一个服务的接口结果返回加一个Header：
 * 因为不是每个应用都安装了tuzhi-security这个包，只是tuzhi-auth-sys安装了这个包，
 * 然后网关调用tuzhi-auth-sys在做鉴权（注意这个鉴权是请求过来时，另外发现的鉴权请求，response也是不一样的，跟原请求的区分开的）；
 * 则给每一个服务的接口结果返回加一个Header还是放在网关这里先了
 * <p>
 * 感觉 tuzhi-security（这里有个web过滤器） 不用单独抽出来，tuzhi-auth-sys合在一起就可以了（过滤器直接放在这个项目）
 *
 * @Description token过滤器
 * @date 2019/12/12 13:55
 */
@Slf4j
@Component
public class GateWayAuthFilter implements GlobalFilter, Ordered {


    @Autowired
    GatewayConfig gatewayConfig;
    @Autowired
    AuthService authService;
    @Autowired
    AuthTokenService authTokenService;
    @Autowired
    TokenServiceImpl tokenService;

    public static final String REFRESH_TOKEN = "Refresh-Token";

    /**
     * token过滤
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String uri = request.getURI().getPath();
        System.out.println("===================="+uri);
        String token = ServletUtils.getHeader(request, AUTHORIZE_TOKEN);
//        ServerHttpRequest host = exchange.getRequest().mutate().header(AppConstant.source_header_name, gatewayConfig.getSource()).build();
        ServerHttpRequest host = exchange.getRequest().mutate().build();
        //将现在的request 变成 change对象
        ServerWebExchange build = exchange.mutate().request(host).build();
        //不需要权限的请求，直接转发访问
        if (authService.isPermitUri4NoAuthUrl(uri) || true) {
            //log.debug("不拦截地址{}", uri);
            if(StringTzUtil.isNotBlankNull(token)){
                response.getHeaders().set(REFRESH_TOKEN, token);
            }
            return chain.filter(build);
        }
        //需要登录
        if (StringTzUtil.isBlankNull(token)) {
            //鉴权内部接口调用
            String sign = ServletUtils.getHeader(request, "sign");
            Long timestamp = ServletUtils.getHeader4Long(request, "timestamp");
            boolean result = authService.verifySignature(sign, timestamp);
            if (result) {
                log.debug("验证签名通过");
                return chain.filter(build);
            }
        }
        //验证token
        LoginUserBO loginUserBO = authTokenService.getLoginUser(token);//根据token获取用户信息
        ResultBO resultBO;
        if (loginUserBO == null) {
            log.debug("token过期!");
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            resultBO = ResultHelper.error(ResultConstant.ERR_TOKEN_ERR.getCode(), ResultConstant.ERR_TOKEN_ERR.getMsg());
            DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONBytes(resultBO));
            return response.writeWith(Mono.just(buffer));
        }
        log.info("call checkAuth:uri:{},token:{}", uri, "****");
        // TODO: 2025/1/10 监权是否有接口的访问权限
        String refreshToken = tokenService.tokenIsExpRefresh(token);
        response.getHeaders().set(REFRESH_TOKEN, refreshToken);
        return chain.filter(exchange);

    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

}
